package com.linkgie.galaxyframework.utils;

import java.lang.reflect.Array;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.function.IntPredicate;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

public final class CollectionUtils {

	private CollectionUtils() {
	}

	public static final <T> Set<T> emptySet() {
		return Collections.emptySet();
	}

	public static final <T> List<T> emptyList() {
		return Collections.emptyList();
	}

	public static final <T> Iterator<T> emptyIterator() {
		return Collections.emptyIterator();
	}

	/**
	 * 对数组求和；
	 * <p>
	 * 注：此方法不处理溢出；
	 * 
	 * @param items
	 * @return
	 */
	public static long sum(long[] items) {
		long sum = 0;
		for (long c : items) {
			sum += c;
		}
		return sum;
	}

	/**
	 * 对数组求和；
	 * <p>
	 * 注：此方法不处理溢出；
	 * 
	 * @param items 数组；
	 * @param from  起始位置（含）；
	 * @param to    截止位置（不含）；
	 * @return
	 */
	public static long sum(long[] items, int from, int to) {
		long sum = 0;
		for (int i = from; i < to && i < items.length; i++) {
			sum += items[i];
		}
		return sum;
	}

	public static long[] concat(long[] items0, long[] items1) {
		long[] newItems = (long[]) Array.newInstance(long.class, items0.length + items1.length);
		System.arraycopy(items0, 0, newItems, 0, items0.length);
		System.arraycopy(items1, 0, newItems, items0.length, items1.length);
		return newItems;
	}

	/**
	 * 连接指定的对象，返回按参数顺序排列的包含所有参数元素的新数组；
	 * 
	 * @param <T>
	 * @param type
	 * @param item
	 * @param items
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] concat(Class<T> type, T item, T... items) {
		if (item == null) {
			return items == null ? null : items.clone();
		}
		if (items == null) {
			T[] newItems = (T[]) Array.newInstance(type, 1);
			newItems[0] = item;
			return newItems;
		}
		T[] newItems = (T[]) Array.newInstance(type, 1 + items.length);
		newItems[0] = item;
		System.arraycopy(items, 0, newItems, 1, items.length);
		return newItems;
	}

	public static <T> T[] concat(T[] array1, T newElement, Class<T> clazz) {
		@SuppressWarnings("unchecked")
		T[] newArray = (T[]) Array.newInstance(clazz, array1.length + 1);
		System.arraycopy(array1, 0, newArray, 0, array1.length);
		newArray[array1.length] = newElement;
		return newArray;
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] concat(T[] items0, T... items1) {
		if (items0 == null) {
			return items1 == null ? null : items1.clone();
		}
		if (items1 == null) {
			return items0.clone();
		}
		T[] newItems = (T[]) Array.newInstance(items0.getClass().getComponentType(), items0.length + items1.length);
		System.arraycopy(items0, 0, newItems, 0, items0.length);
		System.arraycopy(items1, 0, newItems, items0.length, items1.length);
		return newItems;
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] concat(T[]... itemsArray) {
		if (itemsArray == null || itemsArray.length == 0) {
			return null;
		}
		Class<T> componentType = null;
		List<T> combinatedItems = new ArrayList<>();
		for (int i = 0; i < itemsArray.length; i++) {
			if (itemsArray[i] == null) {
				continue;
			}
			if (componentType == null) {
				componentType = (Class<T>) itemsArray[i].getClass().getComponentType();
			}
			T[] items = itemsArray[i];
			for (int j = 0; j < items.length; j++) {
				if (items[j] != null) {
					combinatedItems.add(items[j]);
				}
			}
		}
		if (componentType == null) {
			// 空的参数；
			return null;
		}
		return toArray(combinatedItems, componentType);
	}

	public static <T> Concator<T> concat(@SuppressWarnings("unchecked") T... elements) {
		return new Concator<T>(elements);
	}

	public static <T> Concator<T> concator(@SuppressWarnings("unchecked") T... elements) {
		return new Concator<T>(elements);
	}

	public static <T> List<T> concat(Collection<T> items1, T item) {
		ArrayList<T> newList = items1 == null ? new ArrayList<>() : new ArrayList<>(items1);
		newList.add(item);
		newList.trimToSize();

		return newList;
	}

	public static <T> List<T> concat(Collection<T> items1, T item1, T item2) {
		ArrayList<T> newList = items1 == null ? new ArrayList<>() : new ArrayList<>(items1);
		newList.add(item1);
		newList.add(item2);
		newList.trimToSize();

		return newList;
	}

	public static <T> List<T> concat(Collection<T> items1, T[] items) {
		ArrayList<T> newList = items1 == null ? new ArrayList<>() : new ArrayList<>(items1);
		if (items != null) {
			for (T item : items) {
				newList.add(item);
			}
		}
		newList.trimToSize();

		return newList;
	}

	public static <T> Collection<T> concat(Collection<T> items1, Collection<T> items2) {
		if (isEmpty(items1) && isEmpty(items2)) {
			return Collections.emptyList();
		}
		int size = (items1 == null ? 0 : items1.size()) + (items2 == null ? 0 : items2.size());
		ArrayList<T> newList = new ArrayList<>(size);
		if (items1 != null) {
			newList.addAll(items1);
		}
		if (items2 != null) {
			newList.addAll(items2);
		}
		newList.trimToSize();

		return newList;
	}

	public static <T> List<T> concat(List<T> items1, List<T> items2) {
		if (isEmpty(items1) && isEmpty(items2)) {
			return Collections.emptyList();
		}
		int size = (items1 == null ? 0 : items1.size()) + (items2 == null ? 0 : items2.size());
		ArrayList<T> newList = new ArrayList<>(size);
		if (items1 != null) {
			newList.addAll(items1);
		}
		if (items2 != null) {
			newList.addAll(items2);
		}
		newList.trimToSize();

		return newList;
	}

	@SafeVarargs
	public static <T> List<T> concat(List<T>... itemsList) {
		if (isEmpty(itemsList)) {
			return Collections.emptyList();
		}
		int size = 0;
		for (List<T> items : itemsList) {
			if (items != null) {
				size += items.size();
			}
		}
		ArrayList<T> newList = new ArrayList<>(size);
		for (List<T> items : itemsList) {
			if (items != null) {
				newList.addAll(items);
			}
		}
		newList.trimToSize();

		return newList;
	}

	public static <T> Collection<T> concat(T item, Collection<T> items) {
		if (item == null && isEmpty(items)) {
			return Collections.emptyList();
		}
		int size = (item == null ? 0 : 1) + (items == null ? 0 : items.size());
		ArrayList<T> newList = new ArrayList<>(size);
		if (item != null) {
			newList.add(item);
		}
		if (items != null) {
			newList.addAll(items);
		}
		newList.trimToSize();

		return newList;
	}

	public static <T> List<T> concat(T item, List<T> items) {
		if (item == null && isEmpty(items)) {
			return Collections.emptyList();
		}
		int size = (item == null ? 0 : 1) + (items == null ? 0 : items.size());
		ArrayList<T> newList = new ArrayList<>(size);
		if (item != null) {
			newList.add(item);
		}
		if (items != null) {
			newList.addAll(items);
		}
		newList.trimToSize();

		return newList;
	}

	public static <T> Collection<T> concat(T[] items1, Collection<T> items2) {
		int size = (items1 == null ? 0 : items1.length) + (items2 == null ? 0 : items2.size());
		ArrayList<T> newList = new ArrayList<>(size);
		if (items1 != null) {
			addAll(newList, items1);
		}
		if (items2 != null) {
			newList.addAll(items2);
		}
		newList.trimToSize();

		// ArrayList<T> newList = items2 == null ? new ArrayList<>() : new
		// ArrayList<>(items2);
		// addAll(newList, items1);
		// newList.trimToSize();

		return newList;
	}

	// public static <T> T[] concat(T[] items, T newItem) {
	// @SuppressWarnings("unchecked")
	// T[] newItems = (T[]) Array.newInstance(items.getClass().getComponentType(),
	// items.length + 1);
	// System.arraycopy(items, 0, newItems, 0, items.length);
	// newItems[items.length] = newItem;
	// return newItems;
	// }

	public static <T> long[] castToLong(T[] items, ToLongFunction<T> mapper) {
		if (items == null) {
			return null;
		}
		long[] newItems = new long[items.length];
		for (int i = 0; i < items.length; i++) {
			newItems[i] = mapper.applyAsLong(items[i]);
		}
		return newItems;
	}

	public static <T> int[] castToInt(T[] items, ToIntFunction<T> mapper) {
		if (items == null) {
			return null;
		}
		int[] newItems = new int[items.length];
		for (int i = 0; i < items.length; i++) {
			newItems[i] = mapper.applyAsInt(items[i]);
		}
		return newItems;
	}

	public static <T, R> R[] cast(T[] items, Class<R> clazz, Function<T, R> mapper) {
		if (items == null) {
			return null;
		}
		@SuppressWarnings("unchecked")
		R[] newItems = (R[]) Array.newInstance(clazz, items.length);
		for (int i = 0; i < items.length; i++) {
			newItems[i] = mapper.apply(items[i]);
		}
		return newItems;
	}

	/**
	 * 迭代器转换；
	 * <p>
	 * 
	 * 方法会过滤掉映射为 null 的项；
	 * 
	 * @param <T>
	 * @param <R>
	 * @param items
	 * @param mapper
	 * @return
	 */
	public static <T, R> Iterator<R> cast(Iterator<T> items, Function<T, R> mapper) {
		if (items == null) {
			throw new IllegalArgumentException("NULL items!");
		}
		return new IteratorFilterCaster<>(items, mapper);
	}

	@SuppressWarnings("unchecked")
	public static <T> Iterator<T> cast(Iterator<? extends T> items) {
		if (items == null) {
			return null;
		}
		return (Iterator<T>) items;
	}

	@SuppressWarnings("unchecked")
	public static <T> Collection<T> cast(Collection<? extends T> items) {
		if (items == null) {
			return null;
		}
		return (Collection<T>) items;
	}

	@SuppressWarnings("unchecked")
	public static <T> List<T> cast(List<? extends T> items) {
		if (items == null) {
			return null;
		}
		return (List<T>) items;
	}

	@SuppressWarnings("unchecked")
	public static <T> ListPage<T> cast(ListPage<? extends T> items) {
		if (items == null) {
			return null;
		}
		return (ListPage<T>) items;
	}

	@SuppressWarnings("unchecked")
	public static <T> Set<T> cast(Set<? extends T> items) {
		if (items == null) {
			return null;
		}
		return (Set<T>) items;
	}

	public static <K1, V, K2> Map<K2, V> cast(Map<K1, V> map, Function<K1, K2> keyMapper) {
		Map<K2, V> newMap = new LinkedHashMap<K2, V>();
		for (K1 k1 : map.keySet()) {
			K2 k2 = keyMapper.apply(k1);
			newMap.put(k2, map.get(k1));
		}
		return newMap;
	}

	/**
	 * 转换集合类型；
	 * <p>
	 * 
	 * 返回一个不可修改的指定类型的新集合；
	 * 
	 * @param <T>
	 * @param <R>
	 * @param items
	 * @param mapper
	 * @return
	 */
	public static <T, R> Collection<R> cast(Collection<T> items, Function<T, R> mapper) {
		if (items == null) {
			throw new IllegalArgumentException("NULL items!");
		}

		return new CollectionCaster<T, R>(items, mapper);
	}

	@Deprecated
	public static <T, R> Set<R> castSet(Set<T> items, Function<T, R> mapper) {
		return cast(items, mapper);
	}

	public static <T, R> Set<R> cast(Set<T> items, Function<T, R> mapper) {
		if (items == null) {
			throw new IllegalArgumentException("NULL items!");
		}

		return new SetCaster<T, R>(items, mapper);
	}

	public static <T, R> List<R> cast(List<T> items, Function<T, R> mapper) {
		if (items == null) {
			throw new IllegalArgumentException("NULL items!");
		}

		return toList(items.iterator(), mapper);
	}

	public static <T, R> ListPage<R> cast(ListPage<T> items, Function<T, R> mapper) {
		if (items == null) {
			throw new IllegalArgumentException("NULL items!");
		}

		List<R> newList = toList(items.iterator(), mapper);
		return new ListPageWrapper<>(newList, items);
	}

	public static <T> T[] singleton(T obj, Class<T> clazz) {
		@SuppressWarnings("unchecked")
		T[] items = (T[]) Array.newInstance(clazz, 1);
		items[0] = obj;
		return items;
	}

	public static <T> Set<T> toSet(@SuppressWarnings("unchecked") T... items) {
		return merge(items);
	}

	public static <T> List<T> toList(@SuppressWarnings("unchecked") T... items) {
		if (items == null || items.length == 0) {
			return emptyList();
		}
		ArrayList<T> list = new ArrayList<>(items.length);
		addAll(list, items);
		return list;
	}

	public static <T> List<T> toList(Iterator<T> items) {
		List<T> list = new LinkedList<T>();
		while (items.hasNext()) {
			T t = (T) items.next();
			list.add(t);
		}
		return list;
	}

	public static <T> List<T> toList(Collection<T> items) {
		if (items == null) {
			return null;
		}
		if (items instanceof List) {
			return (List<T>) items;
		}
		return toList(items.iterator());
	}

	public static <T, R> List<R> castToList(Collection<T> items, Function<T, R> mapper) {
		return toList(items.iterator(), mapper);
	}

	public static <T, R> List<R> toList(Iterator<T> items, Function<T, R> mapper) {
		List<R> list = new LinkedList<R>();
		while (items.hasNext()) {
			R r = mapper.apply(items.next());
			list.add(r);
		}
		return list;
	}

	public static <T> T[] toArray(Iterator<T> itr, Class<T> clazz) {
		List<T> list = toList(itr);
		@SuppressWarnings("unchecked")
		T[] items = (T[]) Array.newInstance(clazz, list.size());
		list.toArray(items);
		return items;
	}

	public static <T, R> R[] toArray(Iterator<T> itr, Class<R> clazz, Function<T, R> mapper) {
		List<R> list = toList(itr, mapper);
		@SuppressWarnings("unchecked")
		R[] items = (R[]) Array.newInstance(clazz, list.size());
		list.toArray(items);
		return items;
	}

	/**
	 * 从迭代器读取元素转为指定类型的数组；
	 * 
	 * @param <T>      迭代器的数据项类型；
	 * @param <R>      要转换输出的数组项类型；
	 * @param itr      来源数据的迭代器；
	 * @param clazz    输出的目标数据类型；
	 * @param mapper   将迭代器数据转为目标数据的映射器；
	 * @param maxCount 输出数据项的最大个数，也就是输出数组的最大长度；
	 * @return
	 */
	public static <T, R> R[] toArray(Iterator<T> itr, Class<R> clazz, Function<T, R> mapper, int maxCount) {
		List<R> list = new LinkedList<R>();
		int i = 0;
		while (i < maxCount && itr.hasNext()) {
			R r = mapper.apply(itr.next());
			list.add(r);

			i++;
		}
		@SuppressWarnings("unchecked")
		R[] items = (R[]) Array.newInstance(clazz, list.size());
		list.toArray(items);
		return items;
	}

	public static <T, S extends T> T[] toArray(Collection<S> collection, Class<T> clazz) {
		@SuppressWarnings("unchecked")
		T[] items = (T[]) Array.newInstance(clazz, collection.size());
		collection.toArray(items);
		return items;
	}

	@SuppressWarnings("unchecked")
	public static <T, R> R[] toArray(Collection<T> collection, Class<R> clazz, Function<T, R> mapper) {
		if (isEmpty(collection)) {
			return (R[]) Array.newInstance(clazz, 0);
		}
		R[] items = (R[]) Array.newInstance(clazz, collection.size());
		int i = 0;
		for (T s : collection) {
			items[i] = mapper.apply(s);
			i++;
		}
		return items;
	}

	public static <T, R> R[] castToArray(Collection<T> collection, Class<R> clazz, Function<T, R> mapper) {
		return toArray(collection, clazz, mapper);
	}

	public static <T> Iterator<T> iterator(Iterator<T>[] itemGroups) {
		return new IteratorAggregator<>(itemGroups);
	}

	@SuppressWarnings("unchecked")
	public static <T> Iterator<T> iterator(Iterator<T> itemGroup1, Iterator<T> itemGroup2) {
		return new IteratorAggregator<>(itemGroup1, itemGroup2);
	}

	@SuppressWarnings("unchecked")
	public static <T> Iterator<T> iterator(Iterator<T> itemGroup1, Iterator<T> itemGroup2, Iterator<T> itemGroup3,
			Iterator<T>... itemGroups) {
		Iterator<T>[] groups = new Iterator[3 + itemGroups.length];
		groups[0] = itemGroup1;
		groups[1] = itemGroup2;
		groups[2] = itemGroup3;
		System.arraycopy(itemGroups, 0, groups, 3, itemGroups.length);

		return new IteratorAggregator<>(groups);
	}

	public static <T> Iterator<T> iterator(Collection<Iterator<T>> itemGroups) {
		return new IteratorAggregator<>(itemGroups);
	}

	public static <T> Iterator<T> iterator(@SuppressWarnings("unchecked") T... items) {
		return new ArrayIterator<T>(items);
	}

	public static IntIterator iterator(int[] items) {
		return new IntArrayIterator(items);
	}

	public static LongIterator iterator(long[] items) {
		return new LongArrayIterator(items);
	}

	public static <T, R> Iterator<R> iterator(Collection<T> items, Function<T, R> mapper) {
		if (items == null || items.size() == 0) {
			return Collections.emptyIterator();
		}
		return cast(items.iterator(), mapper);
	}

	public static <T, R> Iterator<R> iterator(T[] items, Function<T, R> mapper) {
		if (items == null || items.length == 0) {
			return Collections.emptyIterator();
		}
		return new ArrayMapperIterator<T, R>(items, mapper);
	}

	public static <T> IntIterator iterator(T[] items, ToIntFunction<T> mapper) {
		if (items == null) {
			return ToIntArrayMapperIterator.EMPTY;
		}
		return new ToIntArrayMapperIterator<T>(items, mapper);
	}

	public static <T> LongIterator iterator(T[] items, ToLongFunction<T> mapper) {
		return new ToLongArrayMapperIterator<T>(items, mapper);
	}

	public static <T> Iterator<T> reverseIterator(T[] items) {
		if (items == null || items.length == 0) {
			return Collections.emptyIterator();
		}
		return new ReverseArrayIterator<>(items);
	}

	public static <T> Iterator<T> reverseIterator(List<T> items) {
		if (items == null || items.size() == 0) {
			return Collections.emptyIterator();
		}
		return new ReverseListIterator<>(items);
	}

	/**
	 * 是否包含有满足指定条件的项目；
	 * 
	 * @param <T>
	 * @param items
	 * @param predicate
	 * @return
	 */
	public static <T> boolean contains(Iterator<T> items, Predicate<T> predicate) {
		return filter(items, predicate).hasNext();
	}

	/**
	 * 是否包含有满足指定条件的项目；
	 * 
	 * @param <T>
	 * @param items
	 * @param predicate
	 * @return
	 */
	public static <T> boolean contains(T[] items, Predicate<T> predicate) {
		return filter(iterator(items), predicate).hasNext();
	}

	/**
	 * 是否包含有满足指定条件的项目；
	 * 
	 * @param <T>
	 * @param items
	 * @param predicate
	 * @return
	 */
	public static <T> boolean contains(Collection<T> items, Predicate<T> predicate) {
		return filter(items.iterator(), predicate).hasNext();
	}

	/**
	 * 过滤所有项，只保留满足断言的项；
	 * 
	 * @param <T>
	 * @param items     过滤前的数据项；
	 * @param predicate 断言函数；
	 * @return
	 */
	public static <T> Iterator<T> filter(Iterator<T> items, Predicate<T> predicate) {
		return new IterableFilter<T>(items, predicate);
	}

	/**
	 * 过滤所有项，只保留满足断言的项；
	 * 
	 * @param <T>
	 * @param items     过滤前的数据项；
	 * @param predicate 断言函数；
	 * @return
	 */
	public static <T> Set<T> filter(Set<T> items, Predicate<T> predicate) {
		return merge(filter(items.iterator(), predicate));
	}

	/**
	 * 过滤所有项，只保留满足断言的项；
	 * 
	 * @param <T>
	 * @param items     过滤前的数据项；
	 * @param predicate 断言函数；
	 * @return 返回包含满足断言的项的数组；
	 *         <p>
	 *         如果 items 参数为 null ，则返回 null ；
	 *         <p>
	 *         如果没有满足断言的项，则返回长度为 0 的空数组；
	 */
	public static <T> T[] filter(T[] items, Predicate<T> predicate) {
		if (items == null) {
			return null;
		}
		@SuppressWarnings("unchecked")
		Class<T> componentType = (Class<T>) items.getClass().getComponentType();
		return toArray(filter(new ArrayIterator<>(items), predicate), componentType);
	}

	/**
	 * 过滤所有项，只保留满足断言的项；
	 * 
	 * @param <T>
	 * @param items     过滤前的数据项；
	 * @param predicate 断言函数；
	 * @return
	 */
	public static <T> List<T> filter(List<T> items, Predicate<T> predicate) {
		return toList(filter(items.iterator(), predicate));
	}

	/**
	 * 过滤转换所有项，只保留断言映射函数返回的非空项；
	 * 
	 * @param <T>
	 * @param items           过滤前的数据项；
	 * @param predicateMapper 断言映射函数；返回所有非空的结果；
	 * @return
	 */
	public static <T, R> R[] filterTo(T[] items, Class<R> resultType, Function<T, R> predicateMapper) {
		return toArray(filterTo(iterator(items), predicateMapper), resultType);
	}

	/**
	 * 过滤转换所有项，只保留断言映射函数返回的非空项；
	 * 
	 * @param <T>
	 * @param items           过滤前的数据项；
	 * @param predicateMapper 断言映射函数；返回所有非空的结果；
	 * @return
	 */
	public static <T, R> List<R> filterTo(Collection<T> items, Function<T, R> predicateMapper) {
		return toList(filterTo(items.iterator(), predicateMapper));
	}

	/**
	 * 过滤转换所有项，只保留断言映射函数返回的非空项；
	 * 
	 * @param <T>
	 * @param items           过滤前的数据项；
	 * @param predicateMapper 断言映射函数；返回所有非空的结果；
	 * @return
	 */
	public static <T, R> Set<R> filterToSet(Collection<T> items, Function<T, R> predicateMapper) {
		return merge(filterTo(items.iterator(), predicateMapper));
	}

	/**
	 * 过滤转换所有项，只保留断言映射函数返回的非空项；
	 * 
	 * @param <T>
	 * @param items           过滤前的数据项；
	 * @param predicateMapper 断言映射函数；返回所有非空的结果；
	 * @return
	 */
	public static <T, R> Set<R> filterToUnmodifiableSet(Collection<T> items, Function<T, R> predicateMapper) {
		return mergeToUnmodifiableSet(filterTo(items.iterator(), predicateMapper));
	}

	/**
	 * 过滤转换所有项，只保留断言映射函数返回的非空项；
	 * 
	 * @param <T>
	 * @param items           过滤前的数据项；
	 * @param predicateMapper 断言映射函数；返回所有非空的结果；
	 * @return
	 */
	public static <T, R> Iterator<R> filterTo(Iterator<T> items, Function<T, R> predicateMapper) {
		return new IteratorFilterCaster<>(items, predicateMapper);
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Set<T> merge(T[] items) {
		if (items == null || items.length == 0) {
			return emptySet();
		}
		LinkedHashSet<T> set = new LinkedHashSet<T>();
		for (T t : items) {
			if (t != null) {
				set.add(t);
			}
		}

		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> Set<T> merge(T[]... itemArrays) {
		if (itemArrays == null || itemArrays.length == 0) {
			return Collections.emptySet();
		}
		LinkedHashSet<T> set = new LinkedHashSet<T>();
		for (int i = 0; i < itemArrays.length; i++) {
			T[] items = itemArrays[i];
			if (items != null) {
				for (T t : items) {
					if (t != null) {
						set.add(t);
					}
				}
			}
		}
		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> Set<T> merge(Collection<T> items1, T... items2) {
		if (isEmpty(items1) && isEmpty(items2)) {
			return Collections.emptySet();
		}
		LinkedHashSet<T> set = new LinkedHashSet<T>();
		if (items1 != null) {
			for (T t : items1) {
				if (t != null) {
					set.add(t);
				}
			}
		}
		if (items2 != null) {
			for (T t : items2) {
				if (t != null) {
					set.add(t);
				}
			}
		}
		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> Set<T> merge(Iterator<T> items1, T... items2) {
		if (isEmpty(items1) && isEmpty(items2)) {
			return Collections.emptySet();
		}
		LinkedHashSet<T> set = new LinkedHashSet<T>();
		if (items1 != null) {
			while (items1.hasNext()) {
				T t = (T) items1.next();
				if (t != null) {
					set.add(t);
				}
			}
		}
		if (items2 != null) {
			for (T t : items2) {
				if (t != null) {
					set.add(t);
				}
			}
		}
		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Set<T> merge(Set<T> items1, Set<T> items2) {
		if (isEmpty(items1) && isEmpty(items2)) {
			return Collections.emptySet();
		}
		LinkedHashSet<T> set = new LinkedHashSet<T>();
		if (items1 != null) {
			for (T t : items1) {
				if (t != null) {
					set.add(t);
				}
			}
		}
		if (items2 != null) {
			for (T t : items2) {
				if (t != null) {
					set.add(t);
				}
			}
		}
		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Set<T> merge(Iterator<T> items) {
		LinkedHashSet<T> set = new LinkedHashSet<T>();
		if (items != null) {
			while (items.hasNext()) {
				T t = (T) items.next();
				if (t != null) {
					set.add(t);
				}
			}
		}
		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T, R> Set<R> merge(T[] items, Function<T, R> mapper) {
		LinkedHashSet<R> set = new LinkedHashSet<R>();
		if (items != null) {
			for (T t : items) {
				R r = mapper.apply(t);
				if (r != null) {
					set.add(r);
				}
			}
		}
		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T, R> Set<R> merge(Collection<T> items, Function<T, R> mapper) {
		LinkedHashSet<R> set = new LinkedHashSet<R>();
		if (items != null) {
			for (T t : items) {
				R r = mapper.apply(t);
				if (r != null) {
					set.add(r);
				}
			}
		}
		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的集合；
	 * <p>
	 * 
	 * 不同于 {@link #unmodifiableSet(Object[])} 方法，此方法返回的 Set 是可编辑的；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T, R> Set<R> merge(Iterator<T> items, Function<T, R> mapper) {
		LinkedHashSet<R> set = new LinkedHashSet<R>();
		if (items != null) {
			while (items.hasNext()) {
				T t = (T) items.next();
				R r = mapper.apply(t);
				if (r != null) {
					set.add(r);
				}
			}
		}
		return set;
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的不可改集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Set<T> mergeToUnmodifiableSet(T[] items) {
		Set<T> set = merge(items);
		if (set == null) {
			return null;
		}
		return Collections.unmodifiableSet(set);
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的不可改集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Set<T> unmodifiableSet(T[] items) {
		Set<T> set = merge(items);
		if (set == null) {
			return null;
		}
		return Collections.unmodifiableSet(set);
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的不可改集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Set<T> mergeToUnmodifiableSet(Collection<T> items) {
		@SuppressWarnings("unchecked")
		Set<T> set = merge(items);
		if (set == null) {
			return null;
		}
		return Collections.unmodifiableSet(set);
	}

	@SuppressWarnings("unchecked")
	public static <T> Set<T> mergeToUnmodifiableSet(Collection<T> items1, T... items2) {
		return Collections.unmodifiableSet(merge(items1, items2));
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的不可改集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Set<T> mergeToUnmodifiableSet(Iterator<T> items) {
		Set<T> set = merge(items);
		if (set == null) {
			return null;
		}
		return Collections.unmodifiableSet(set);
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的不可改集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T, R> Set<R> mergeToUnmodifiableSet(T[] items, Function<T, R> mapper) {
		Set<R> set = merge(items, mapper);
		if (set == null) {
			return null;
		}
		return Collections.unmodifiableSet(set);
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的不可改集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T, R> Set<R> mergeToUnmodifiableSet(Collection<T> items, Function<T, R> mapper) {
		Set<R> set = merge(items, mapper);
		if (set == null) {
			return null;
		}
		return Collections.unmodifiableSet(set);
	}

	/**
	 * 合并重复元素，返回由所有唯一元素组成的不可改集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T, R> Set<R> mergeToUnmodifiableSet(Iterator<T> items, Function<T, R> mapper) {
		Set<R> set = merge(items, mapper);
		if (set == null) {
			return null;
		}
		return Collections.unmodifiableSet(set);
	}

	public static <T> T min(Collection<T> items, Comparator<T> comparator) {
		return min(items.iterator(), comparator);
	}

	public static <T> T min(T[] items, Comparator<T> comparator) {
		return min(iterator(items), comparator);
	}

	public static <T> T min(Iterator<T> items, Comparator<T> comparator) {
		T candidate = items.next();

		while (items.hasNext()) {
			T next = items.next();
			if (comparator.compare(next, candidate) < 0) {
				candidate = next;
			}
		}
		return candidate;
	}

	public static <T> T min(Collection<T> items, ToIntFunction<T> integerize) {
		return min(items.iterator(), integerize);
	}

	public static <T> T min(T[] items, ToIntFunction<T> integerize) {
		return min(iterator(items), integerize);
	}

	public static <T> T min(Iterator<T> items, ToIntFunction<T> integerize) {
		T candidate = items.next();

		while (items.hasNext()) {
			T next = items.next();
			if (compare(next, candidate, integerize) < 0) {
				candidate = next;
			}
		}
		return candidate;
	}

	/**
	 * 比较两个对象的大小；
	 * <p>
	 * 如果第一个参数小，则返回 -1 ;
	 * <p>
	 * 如果两个参数相等，则返回 0 ；
	 * <p>
	 * 如果第一个参数大，则返回 1 ；
	 * 
	 * @param <T>
	 * @param o1
	 * @param o2
	 * @param integerize
	 * @return
	 */
	public static <T> int compare(T o1, T o2, ToIntFunction<T> integerize) {
		int v1 = integerize.applyAsInt(o1);
		int v2 = integerize.applyAsInt(o2);
		return v1 < v2 ? -1 : (v1 == v2 ? 0 : 1);
	}

	/**
	 * 返回数组之间重复出现的元素（交集）；
	 * <p>
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> Set<T> intersect(T[]... itemArrays) {
		Set<T>[] itemSets = cast(itemArrays, Set.class, (items) -> merge(items));
		// 长度最短的集合；
		return intersect(itemSets);
	}

	/**
	 * 返回数组之间重复出现的元素（交集）；
	 * <p>
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Set<T> intersect(Collection<T[]> itemArrays) {
		Collection<Set<T>> itemSets = cast(itemArrays, (items) -> merge(items));
		// 长度最短的集合；
		Set<T> minSet = min(itemSets, (s) -> s.size());
		if (isEmpty(minSet)) {
			return Collections.emptySet();
		}

		Set<T> intersection = minSet;
		for (Set<T> set : itemSets) {
			if (set == minSet) {
				continue;
			}
			intersection = intersectBetween(intersection, set);
			if (intersection.isEmpty()) {
				break;
			}
		}
		return intersection;
	}

	/**
	 * 获取指定集合的交集，即同时出现在所有集合中的元素的集合（交集）；
	 * <p>
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> Set<T> intersect(Set<T>... itemSets) {
		// 长度最短的集合；
		Set<T> minSet = min(itemSets, (s) -> s.size());
		if (isEmpty(minSet)) {
			return Collections.emptySet();
		}

		Set<T> intersection = minSet;
		for (Set<T> set : itemSets) {
			if (set == minSet) {
				continue;
			}
			intersection = intersectBetween(intersection, set);
			if (intersection.isEmpty()) {
				break;
			}
		}
		return intersection;
	}

	private static <T> Set<T> intersectBetween(Set<T> set1, Set<T> set2) {
		if (set1 == set2) {
			return set1;
		}
		Set<T> min;
		Set<T> max;
		if (set1.size() < set2.size()) {
			min = set1;
			max = set2;
		} else {
			min = set2;
			max = set1;
		}
		if (min.isEmpty()) {
			return Collections.emptySet();
		}

		HashSet<T> result = new HashSet<T>();
		for (T t : min) {
			if (max.contains(t)) {
				result.add(t);
			}
		}
		return result;
	}

	/**
	 * 排序并且合并重复元素，返回由所有唯一元素组成的集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> SortedSet<T> sortAndMerge(T[] items) {
		if (items == null || items.length == 0) {
			return Collections.emptySortedSet();
		}
		TreeSet<T> set = new TreeSet<T>();
		for (T t : items) {
			if (t != null) {
				set.add(t);
			}
		}
		return set;
	}

	/**
	 * 排序并且合并重复元素，返回由所有唯一元素组成的集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> SortedSet<T> sortAndMerge(T[] items, Comparator<T> comparator) {
		if (items == null || items.length == 0) {
			return Collections.emptySortedSet();
		}
		TreeSet<T> set = new TreeSet<T>(comparator);
		for (T t : items) {
			if (t != null) {
				set.add(t);
			}
		}
		return set;
	}

	/**
	 * 排序并返回由所有元素组成的集合；
	 * <p>
	 * 
	 * 注意：此方法不改变原来的集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> Collection<T> sort(Collection<T> items, Comparator<T> comparator) {
		return sortToList(items, comparator);
	}

	/**
	 * 排序并返回由所有元素组成的集合；
	 * <p>
	 * 
	 * 注意：此方法不改变原来的集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> List<T> sortToList(Collection<T> items, Comparator<T> comparator) {
		if (items == null || items.size() == 0) {
			return Collections.emptyList();
		}
		List<T> list = toList(items.iterator());
		Collections.sort(list, comparator);
		return list;
	}

	/**
	 * 排序并且合并重复元素，返回由所有唯一元素组成的集合；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> SortedSet<T> sortAndMerge(Collection<T> items) {
		if (items == null || items.size() == 0) {
			return Collections.emptySortedSet();
		}
		TreeSet<T> set = new TreeSet<T>();
		for (T t : items) {
			if (t != null) {
				set.add(t);
			}
		}
		return set;
	}

	/**
	 * 以集合方式比较相等性；
	 * <p>
	 * 
	 * 只有两个集合数量一致，每项都存在两个集合中，则返回 true ；
	 * <p>
	 * 
	 * 比较过程忽略集合中元素的排列顺序；
	 * 
	 * @param <T>
	 * @param items1
	 * @param items2
	 * @return
	 */
	public static <T> boolean equalAsSet(T[] items1, T[] items2) {
		if (isEmpty(items1) && isEmpty(items2)) {
			return true;
		}
		if (items1 == null || items2 == null) {
			return false;
		}

		Set<T> set1 = merge(items1);
		Set<T> set2 = merge(items2);
		return checkEqualityAsSet(set1, set2);
	}

	/**
	 * 以集合方式比较相等性；
	 * <p>
	 * 
	 * 只有两个集合数量一致，每项都存在两个集合中，则返回 true ；
	 * <p>
	 * 
	 * 比较过程忽略集合中元素的排列顺序；
	 * 
	 * @param <T>
	 * @param items1
	 * @param items2
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> boolean equalAsSet(Collection<T> items1, Collection<T> items2) {
		if (isEmpty(items1) && isEmpty(items2)) {
			return true;
		}
		if (items1 == null || items2 == null) {
			return false;
		}

		Set<T> set1 = (items1 instanceof Set) ? (Set<T>) items1 : merge(items1);
		Set<T> set2 = (items2 instanceof Set) ? (Set<T>) items2 : merge(items2);
		return checkEqualityAsSet(set1, set2);
	}

	/**
	 * 以集合方式比较相等性；
	 * <p>
	 * 
	 * 只有两个集合数量一致，每项都存在两个集合中，则返回 true ；
	 * <p>
	 * 
	 * 比较过程忽略集合中元素的排列顺序；
	 * 
	 * @param <T>
	 * @param items1
	 * @param items2
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> boolean equalAsSet(Collection<T> items1, T[] items2) {
		if (isEmpty(items1) && isEmpty(items2)) {
			return true;
		}
		if (items1 == null || items2 == null) {
			return false;
		}

		Set<T> set1 = (items1 instanceof Set) ? (Set<T>) items1 : merge(items1);
		Set<T> set2 = merge(items2);
		return checkEqualityAsSet(set1, set2);
	}

	/**
	 * 以集合方式比较相等性；
	 * <p>
	 * 
	 * 只有两个集合数量一致，每项都存在两个集合中，则返回 true ；
	 * <p>
	 * 
	 * 比较过程忽略集合中元素的排列顺序；
	 * 
	 * @param <T>
	 * @param set1
	 * @param items
	 * @return
	 */
	public static <T> boolean equalAsSet(Set<T> set1, T[] items) {
		if (isEmpty(set1) && isEmpty(items)) {
			return true;
		}
		if (set1 == null || items == null) {
			return false;
		}

		Set<T> set2 = merge(items);
		return checkEqualityAsSet(set1, set2);
	}

	/**
	 * 以集合方式比较相等性；
	 * <p>
	 * 
	 * 只有两个集合数量一致，每项都存在两个集合中，则返回 true ；
	 * <p>
	 * 
	 * 比较过程忽略集合中元素的排列顺序；
	 * 
	 * @param <T>
	 * @param set1
	 * @param set2
	 * @return
	 */
	public static <T> boolean equalAsSet(Set<T> set1, Set<T> set2) {
		if (isEmpty(set1) && isEmpty(set2)) {
			return true;
		}
		if (set1 == null || set2 == null) {
			return false;
		}

		return checkEqualityAsSet(set1, set2);
	}

	/**
	 * 是否为空；
	 * <p>
	 * 当为 null 或长度为 0 时，返回 true；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> boolean isEmpty(Collection<T> items) {
		return items == null || items.size() == 0;
	}

	/**
	 * 是否为空；
	 * <p>
	 * 当为 null 或长度为 0 时，返回 true；
	 * 
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> boolean isEmpty(Iterator<T> items) {
		return items == null || !items.hasNext();
	}

	public static <T> boolean isEmpty(T[] items) {
		return items == null || items.length == 0;
	}

	/**
	 * 以集合方式比较相等性；
	 * <p>
	 * 
	 * 只有两个集合数量一致，每项都存在两个集合中，则返回 true ；
	 * <p>
	 * 
	 * 比较过程忽略集合中元素的排列顺序；
	 * 
	 * @param <T>
	 * @param set1
	 * @param set2
	 * @return
	 */
	private static <T> boolean checkEqualityAsSet(Set<T> set1, Set<T> set2) {
		if (set1.size() != set2.size()) {
			return false;
		}
		for (T t : set1) {
			if (!set2.contains(t)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T> List<T> newArrayList(T[] items) {
		ArrayList<T> arrayList = new ArrayList<>();
		for (T e : items) {
			arrayList.add(e);
		}
		return arrayList;
	}

	/**
	 * @param <T>
	 * @param items
	 * @return
	 */
	public static <T, R> List<R> newArrayList(T[] items, Function<T, R> mapper) {
		ArrayList<R> arrayList = new ArrayList<>();
		for (T e : items) {
			arrayList.add(mapper.apply(e));
		}
		return arrayList;
	}

	public static <T> List<T> unmodifiableList(T[] items) {
		if (items == null) {
			return Collections.emptyList();
		}
		return unmodifiableList(items, 0, items.length);
	}

	public static <T> List<T> unmodifiableList(T[] items, int offset, int count) {
		if (items == null) {
			return Collections.emptyList();
		}
		if (offset < 0) {
			throw new IllegalArgumentException("The argument \"offset\" is negative!");
		}
		if (count < 0) {
			throw new IllegalArgumentException("The argument \"count\" is negative!");
		}
		if (offset + count > items.length) {
			throw new IndexOutOfBoundsException("Index specified by arguments is out of bound!");
		}

		if (count == 0) {
			return Collections.emptyList();
		}
		return new ReadonlyArrayList<T>(items, offset, count);
	}

	/**
	 * 反转数组； <br>
	 * 
	 * @param <T>
	 * @param items
	 */
	public static <T> void reverse(T[] items) {
		if (items == null || items.length < 2) {
			return;
		}
		T t;
		for (int i = 0, j = items.length - 1; i < j; i++, j--) {
			t = items[i];
			items[i] = items[j];
			items[j] = t;
		}
	}

	public static void reverse(long[] items) {
		if (items == null || items.length < 2) {
			return;
		}

		long t;
		for (int i = 0, j = items.length - 1; i < j; i++, j--) {
			t = items[i];
			items[i] = items[j];
			items[j] = t;
		}
	}

	/**
	 * 判断两个数组是否一致；
	 * <p>
	 * 
	 * 如果两个数组都为 null，则返回 true；
	 * <p>
	 * 如果两个数组只有其中之一为 null，则返回 false；
	 * <p>
	 * 如果两个数组的长度不一致，则返回 false；
	 * <p>
	 * 如果两个数组在相同的位置上的元素都相同，则返回 true，否则返回 false；
	 * 
	 * @param item0
	 * @param item1
	 * @return true 表示两个数组内容一致；
	 */
	public static boolean equals(int[] item0, int[] item1) {
		return Arrays.equals(item0, item1);
	}

	public static int max(int[] values) {
		if (values == null || values.length == 0) {
			throw new IllegalArgumentException("No values!");
		}
		int value = Integer.MIN_VALUE;
		for (int l : values) {
			if (l > value) {
				value = l;
			}
		}
		return value;
	}

	public static long max(long[] values) {
		if (values == null || values.length == 0) {
			throw new IllegalArgumentException("No values!");
		}
		long value = Long.MIN_VALUE;
		for (long l : values) {
			if (l > value) {
				value = l;
			}
		}
		return value;
	}

	/**
	 * 将所有的元素都加入到指定的集合中；
	 * 
	 * @param <T>
	 * @param collection
	 * @param newElements
	 */
	@SuppressWarnings("unchecked")
	public static <T> void addAll(Collection<T> collection, T... newElements) {
		addAll(collection, (e) -> true, newElements);
	}

	/**
	 * 将所有的元素都加入到指定的集合中；
	 * 
	 * @param <T>
	 * @param collection
	 * @param newElements
	 */
	@SuppressWarnings("unchecked")
	public static <T> void addAll(Collection<T> collection, Predicate<T> predicate, T... newElements) {
		if (newElements == null) {
			return;
		}
		for (T e : newElements) {
			if (predicate.test(e)) {
				collection.add(e);
			}
		}
	}

	/**
	 * 将值列表映射为 map ；
	 * 
	 * @param <K>
	 * @param <V>
	 * @param collection
	 * @param function
	 * @return
	 */
	public static <K, V> Map<K, V> map(Collection<V> collection, Function<V, K> function) {
		HashMap<K, V> map = new HashMap<>();
		for (V v : collection) {
			map.put(function.apply(v), v);
		}
		return map;
	}

	/**
	 * 将值列表映射为 map ；
	 * 
	 * @param <K>        键的类型；
	 * @param <V>        值的类型；
	 * @param collection 值列表；
	 * @param outputMap  结果输出的 Map 对象；
	 * @param function   映射函数；
	 */
	public static <K, V> void mapTo(Collection<V> collection, Map<K, V> outputMap, Function<V, K> function) {
		for (V v : collection) {
			outputMap.put(function.apply(v), v);
		}
	}

	public static <K, V> SortedMap<K, V> sortedMap(Collection<V> collection, Function<V, K> function) {
		SortedMap<K, V> map = new TreeMap<>();
		for (V v : collection) {
			map.put(function.apply(v), v);
		}
		return map;
	}

	public static <K, V> Map<K, V> map(V[] collection, Function<V, K> function) {
		HashMap<K, V> map = new HashMap<>();
		for (V v : collection) {
			map.put(function.apply(v), v);
		}
		return map;
	}

	public static <K, V> void mapTo(V[] collection, Map<K, V> outputMap, Function<V, K> function) {
		for (V v : collection) {
			outputMap.put(function.apply(v), v);
		}
	}

	public static <K, V> SortedMap<K, V> sortedMap(V[] collection, Function<V, K> function) {
		SortedMap<K, V> map = new TreeMap<>();
		for (V v : collection) {
			map.put(function.apply(v), v);
		}
		return map;
	}

	public static <T> int indexOf(T[] arrays, Predicate<T> predicate) {
		return indexOf(arrays, 0, predicate);
	}

	public static <T> int indexOf(T[] arrays, int from, Predicate<T> predicate) {
		for (int i = from; i < arrays.length; i++) {
			if (predicate.test(arrays[i])) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * 查找首个符合条件的值；如果没有匹配值，则返回 null；
	 * 
	 * @param items
	 * @param predicate
	 * @return
	 */
	public static Integer findFirst(IntIterator items, IntPredicate predicate) {
		return findFirst(items, 0, predicate);
	}

	/**
	 * 查找首个符合条件的值；如果没有匹配值，则返回 null；
	 * 
	 * @param items
	 * @param skip      在开始进行匹配之前要忽略的个数；
	 * @param predicate
	 * @return
	 */
	public static Integer findFirst(IntIterator items, int skip, IntPredicate predicate) {
		int i = 0;
		while (items.hasNext()) {
			int v = items.next();
			if (i >= skip && predicate.test(v)) {
				return v;
			}
			i++;
		}
		return null;
	}

	/**
	 * 查找首个符合条件的值；如果没有匹配值，则返回 null；
	 * 
	 * @param items
	 * @param predicate
	 * @return
	 */
	public static Long findFirst(LongIterator items, LongPredicate predicate) {
		return findFirst(items, 0, predicate);
	}

	/**
	 * 查找首个符合条件的值；如果没有匹配值，则返回 null；
	 * 
	 * @param items
	 * @param skip      在开始进行匹配之前要忽略的个数；
	 * @param predicate
	 * @return
	 */
	public static Long findFirst(LongIterator items, int skip, LongPredicate predicate) {
		int i = 0;
		while (items.hasNext()) {
			long v = items.next();
			if (i >= skip && predicate.test(v)) {
				return v;
			}
			i++;
		}
		return null;
	}

	/**
	 * 查找首个值；如果没有，则返回 null；
	 * 
	 * @param items
	 * @param predicate
	 * @return
	 */
	public static <T> T findFirst(Iterator<T> items) {
		return items.hasNext() ? items.next() : null;
	}

	public static <T> T findFirst(Iterator<T> items, Predicate<T> predicate) {
		return findFirst(items, 0, predicate);
	}

	/**
	 * 查找首个符合条件的值；如果没有匹配值，则返回 null；
	 * 
	 * @param <T>
	 * @param items
	 * @param skip      在开始进行匹配之前要忽略的个数；
	 * @param predicate
	 * @return
	 */
	public static <T> T findFirst(Iterator<T> items, int skip, Predicate<T> predicate) {
		int i = 0;
		while (items.hasNext()) {
			T t = (T) items.next();
			if (i >= skip && predicate.test(t)) {
				return t;
			}
			i++;
		}
		return null;
	}

	public static <T> T findFirst(T[] arrays, Predicate<T> predicate) {
		return findFirst(arrays, 0, predicate);
	}

	public static <T> T findFirst(T[] arrays, int from, Predicate<T> predicate) {
		for (int i = from; i < arrays.length; i++) {
			if (predicate.test(arrays[i])) {
				return arrays[i];
			}
		}
		return null;
	}

	public static <T> T findFirst(Collection<T> items) {
		return findFirst(items.iterator());
	}

	public static <T> T findFirst(Collection<T> items, Predicate<T> predicate) {
		return findFirst(items.iterator(), 0, predicate);
	}

	public static <T> T findFirst(Collection<T> items, int from, Predicate<T> predicate) {
		return findFirst(items.iterator(), from, predicate);
	}

	// ------------------ 内部类型 ---------------------//

	private static class IterableFilter<T> implements Iterator<T> {

		private Iterator<T> items;

		private Predicate<T> predicate;

		private T current;

		public IterableFilter(Iterator<T> items, Predicate<T> predicate) {
			this.items = items;
			this.predicate = predicate;

			seekToNext();
		}

		private void seekToNext() {
			while (items.hasNext()) {
				T nextItem = items.next();
				if (predicate.test(nextItem)) {
					this.current = nextItem;
					return;
				}
			}
			this.current = null;
		}

		@Override
		public boolean hasNext() {
			return this.current != null;
		}

		@Override
		public T next() {
			T item = this.current;
			seekToNext();
			return item;
		}

	}

	private static class IteratorAggregator<T> implements Iterator<T> {

		private Iterator<Iterator<T>> iterators;

		private Iterator<T> current;

		public IteratorAggregator(@SuppressWarnings("unchecked") Iterator<T>... itemGroups) {
			this(Arrays.asList(itemGroups));
		}

		public IteratorAggregator(Collection<Iterator<T>> itemGroups) {
			this.iterators = itemGroups.iterator();
			nextGroup();
		}

		/**
		 * 移到下一个有效的迭代器；
		 */
		private void nextGroup() {
			Iterator<T> its = this.current;
			while (its == null || !its.hasNext()) {
				if (iterators.hasNext()) {
					its = iterators.next();
				} else {
					this.current = null;
					return;
				}
			}
			this.current = its;
		}

		@Override
		public boolean hasNext() {
			if (this.current == null) {
				return false;
			}
			if (this.current.hasNext()) {
				return true;
			}
			nextGroup();
			if (this.current == null) {
				return false;
			}
			return true;
		}

		@Override
		public T next() {
			if (this.current == null) {
				return null;
			}
			if (this.current.hasNext()) {
				return this.current.next();
			}
			nextGroup();
			if (this.current == null) {
				return null;
			}
			return this.current.next();
		}

	}

	private static class ArrayIterator<E> implements Iterator<E> {

		private E[] items;

		private int cursor = 0;

		public ArrayIterator(E[] items) {
			this.items = items;
		}

		@Override
		public boolean hasNext() {
			return cursor < items.length;
		}

		@Override
		public E next() {
			if (cursor < items.length) {
				return items[cursor++];
			}
			return null;
		}

	}

	private static class ReverseArrayIterator<E> implements Iterator<E> {

		private E[] items;

		private int cursor = 0;

		public ReverseArrayIterator(E[] items) {
			this.items = items;
			cursor = items.length - 1;
		}

		@Override
		public boolean hasNext() {
			return cursor > -1;
		}

		@Override
		public E next() {
			if (cursor > -1) {
				return items[cursor--];
			}
			return null;
		}

	}

	private static class ReverseListIterator<E> implements Iterator<E> {

		private List<E> items;

		private int cursor = 0;

		public ReverseListIterator(List<E> items) {
			this.items = items;
			cursor = items.size() - 1;
		}

		@Override
		public boolean hasNext() {
			return cursor > -1;
		}

		@Override
		public E next() {
			if (cursor > -1) {
				return items.get(cursor--);
			}
			return null;
		}

	}

	private static class IntArrayIterator implements IntIterator {

		private int[] items;

		private int cursor;

		public IntArrayIterator(int[] items) {
			this.items = items;
		}

		@Override
		public boolean hasNext() {
			return cursor < items.length;
		}

		@Override
		public int next() {
			if (cursor < items.length) {
				return items[cursor++];
			}
			throw new IllegalStateException("No next!");
		}

	}

	private static class LongArrayIterator implements LongIterator {

		private long[] items;

		private int cursor;

		public LongArrayIterator(long[] items) {
			this.items = items;
		}

		@Override
		public boolean hasNext() {
			return cursor < items.length;
		}

		@Override
		public long next() {
			if (cursor < items.length) {
				return items[cursor++];
			}
			throw new IllegalStateException("No next!");
		}

	}

	private static class ArrayMapperIterator<E, R> implements Iterator<R> {

		private E[] items;

		private Function<E, R> mapper;

		private int cursor;

		public ArrayMapperIterator(E[] items, Function<E, R> mapper) {
			this.items = items;
			this.mapper = mapper;
		}

		@Override
		public boolean hasNext() {
			return cursor < items.length;
		}

		@Override
		public R next() {
			if (cursor < items.length) {
				return mapper.apply(items[cursor++]);
			}
			return null;
		}

	}

	private static class ToLongArrayMapperIterator<E> implements LongIterator {

		private E[] items;

		private ToLongFunction<E> mapper;

		private int cursor;

		public ToLongArrayMapperIterator(E[] items, ToLongFunction<E> mapper) {
			this.items = items;
			this.mapper = mapper;
		}

		@Override
		public boolean hasNext() {
			return cursor < items.length;
		}

		@Override
		public long next() {
			if (cursor < items.length) {
				return mapper.applyAsLong(items[cursor++]);
			}
			throw new IllegalStateException("No next!");
		}

	}

	private static class ToIntArrayMapperIterator<E> implements IntIterator {

		public static final ToIntArrayMapperIterator<?> EMPTY = new ToIntArrayMapperIterator<>(new Object[0], (e) -> 0);

		private E[] items;

		private ToIntFunction<E> mapper;

		private int cursor = 0;

		public ToIntArrayMapperIterator(E[] items, ToIntFunction<E> mapper) {
			this.items = items;
			this.mapper = mapper;
		}

		@Override
		public boolean hasNext() {
			return cursor < items.length;
		}

		@Override
		public int next() {
			if (cursor < items.length) {
				return mapper.applyAsInt(items[cursor++]);
			}
			throw new IllegalStateException("No next!");
		}

	}

	private static class CollectionCaster<T, R> extends AbstractCollection<R> {

		private Collection<T> items;
		private Function<T, R> mapper;

		public CollectionCaster(Collection<T> items, Function<T, R> mapper) {
			this.items = items;
			this.mapper = mapper;
		}

		@Override
		public Iterator<R> iterator() {
			return new IteratorCaster<T, R>(items.iterator(), mapper);
		}

		@Override
		public int size() {
			return items.size();
		}

	}

	private static class SetCaster<T, R> extends AbstractSet<R> {

		private Set<T> items;
		private Function<T, R> mapper;

		public SetCaster(Set<T> items, Function<T, R> mapper) {
			this.items = items;
			this.mapper = mapper;
		}

		@Override
		public Iterator<R> iterator() {
			return new IteratorCaster<T, R>(items.iterator(), mapper);
		}

		@Override
		public int size() {
			return items.size();
		}

	}

	private static class IteratorCaster<T, R> implements Iterator<R> {

		private Iterator<T> items;
		private Function<T, R> mapper;

		public IteratorCaster(Iterator<T> items, Function<T, R> mapper) {
			this.items = items;
			this.mapper = mapper;
		}

		@Override
		public boolean hasNext() {
			return items.hasNext();
		}

		@Override
		public R next() {
			T next = items.next();
			return mapper.apply(next);
		}

	}

	/**
	 * 带过滤的迭代转换器；
	 * <p>
	 * 
	 * 只返回非空项；
	 * <p>
	 * 
	 * @author huanghaiquan
	 *
	 * @param <T>
	 * @param <R>
	 */
	private static class IteratorFilterCaster<T, R> implements Iterator<R> {

		private Iterator<T> items;

		private R nextItem;

		private Function<T, R> mapper;

		public IteratorFilterCaster(Iterator<T> items, Function<T, R> mapper) {
			this.items = items;
			this.mapper = mapper;

			seekToNext();
		}

		private void seekToNext() {
			while (items.hasNext()) {
				T item = (T) items.next();
				// 不处理原始空值，由映射函数处理；
				R nextItem = mapper.apply(item);
				if (nextItem != null) {
					this.nextItem = nextItem;
					return;
				}
			}
			// 已搜索到最后；
			this.nextItem = null;
		}

		@Override
		public boolean hasNext() {
			return this.nextItem != null;
		}

		@Override
		public R next() {
			R item = this.nextItem;
			seekToNext();
			return item;
		}

	}

	public static class Concator<T> {
		private ArrayList<T> list = new ArrayList<T>();

		private Class<T> componentType;

		@SuppressWarnings("unchecked")
		private Concator(T... elements) {
			if (elements == null) {
				throw new IllegalArgumentException("Cannot concat null elements!");
			}
			this.componentType = (Class<T>) elements.getClass().getComponentType();
			addAll(elements);
		}

		@SuppressWarnings("unchecked")
		public Concator<T> concat(T... elements) {
			addAll(elements);
			return this;
		}

		public T[] toArray() {
			return CollectionUtils.toArray(list, componentType);
		}

		/**
		 * 以数组形式返回所有非空元素；
		 * 
		 * @return
		 */
		public T[] toNotNullElementsArray() {
			return CollectionUtils.toArray(notNullElements(), componentType);
		}

		public Iterator<T> notNullElements() {
			return CollectionUtils.filter(list.iterator(), (item) -> item != null);
		}

		public List<T> toList() {
			return list;
		}

		@SuppressWarnings("unchecked")
		private void addAll(T... elements) {
			if (elements != null) {
				for (T e : elements) {
					list.add(e);
				}
			}
		}
	}

	static void checkPagination(long pageIndex, long pageSize, Long totalSize) {
		if (pageIndex < 0) {
			// 分页索引不能小于 0 ；
			throw new IllegalArgumentException("Page index is negative!");
		}
	
		if (pageSize <= 0) {
			// 页大小不能小于等于 0 ；
			throw new IllegalArgumentException("Page size is negative or zero!");
		}
	}

	static void checkListPagination(int listSize, long pageIndex, long pageSize, Long totalSize) {
		checkPagination(pageIndex, pageSize, totalSize);

		if (totalSize != null && totalSize.longValue() >= 0 && totalSize.longValue() < listSize) {
			// 总数可以为空，但不能小于当前列表的数量 ；
			throw new IllegalArgumentException(
					"The total size [" + totalSize + "] is less than the list size!");
		}
		if (pageSize < listSize) {
			// 设置页大小不能小于当前列表页的大小；
			throw new IllegalArgumentException("The page size [" + pageSize + "] is less than the list size!");
		}
	}
}
